package heatmap

import (
	

	
	
	
	
	
	
	
	
)

// DataFormatMode represents the data format modes.
type DataFormatMode string

const (
	// Grafana does the bucketing by going through all time series values
	TimeSeriesBuckets DataFormatMode = "tsbuckets"

	// Each time series already represents a Y-Axis bucket.
	TimeSeries DataFormatMode = "timeseries"
)

// LegendOption allows to configure a legend.
type LegendOption uint16

const (
	// Hide keeps the legend from being displayed.
	Hide LegendOption = iota
)

// Option represents an option that can be used to configure a heatmap panel.
type Option func(stat *Heatmap) error

// Heatmap represents a heatmap panel.
type Heatmap struct {
	Builder *sdk.Panel
}

// New creates a new heatmap panel.
func ( string,  ...Option) (*Heatmap, error) {
	 := &Heatmap{Builder: sdk.NewHeatmap()}
	.Builder.IsNew = false
	.Builder.HeatmapPanel.Cards = struct {
		 *float64 `json:"cardPadding"`
		   *float64 `json:"cardRound"`
	}{}
	.Builder.HeatmapPanel.Color = struct {
		   string   `json:"cardColor"`
		  string   `json:"colorScale"`
		 string   `json:"colorScheme"`
		    float64  `json:"exponent"`
		         *float64 `json:"min,omitempty"`
		         *float64 `json:"max,omitempty"`
		        string   `json:"mode"`
	}{
		:   "#b4ff00",
		:  "sqrt",
		: "interpolateSpectral",
		:    0.5,
		:        "spectrum",
	}
	.Builder.HeatmapPanel.Legend = struct {
		 bool `json:"show"`
	}{
		: true,
	}
	.Builder.HeatmapPanel.Tooltip = struct {
		          bool `json:"show"`
		 bool `json:"showHistogram"`
	}{
		:          true,
		: true,
	}
	.Builder.HeatmapPanel.XAxis = struct {
		 bool `json:"show"`
	}{
		: true,
	}
	.Builder.HeatmapPanel.YBucketBound = "auto"

	for ,  := range append(defaults(), ...) {
		if  := ();  != nil {
			return nil, 
		}
	}

	return , nil
}

func defaults() []Option {
	return []Option{
		Span(6),
		DataFormat(TimeSeriesBuckets),
		HideZeroBuckets(),
		HighlightCards(),
		defaultYAxis(),
	}
}

func defaultYAxis() Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.YAxis = *axis.New().Builder

		return nil
	}
}

// Links adds links to be displayed on this panel.
func ( ...links.Link) Option {
	return func( *Heatmap) error {
		.Builder.Links = make([]sdk.Link, 0, len())

		for ,  := range  {
			.Builder.Links = append(.Builder.Links, .Builder)
		}

		return nil
	}
}

// DataSource sets the data source to be used by the panel.
func ( string) Option {
	return func( *Heatmap) error {
		.Builder.Datasource = &sdk.DatasourceRef{LegacyName: }

		return nil
	}
}

// DataFormat sets how the data should be interpreted.
func ( DataFormatMode) Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.DataFormat = string()

		return nil
	}
}

// WithPrometheusTarget adds a prometheus query to the graph.
func ( string,  ...prometheus.Option) Option {
	 := prometheus.New(, ...)

	return func( *Heatmap) error {
		.Builder.AddTarget(&sdk.Target{
			RefID:          .Ref,
			Hide:           .Hidden,
			Expr:           .Expr,
			IntervalFactor: .IntervalFactor,
			Interval:       .Interval,
			Step:           .Step,
			LegendFormat:   .LegendFormat,
			Instant:        .Instant,
			Format:         .Format,
		})

		return nil
	}
}

// WithGraphiteTarget adds a Graphite target to the table.
func ( string,  ...graphite.Option) Option {
	 := graphite.New(, ...)

	return func( *Heatmap) error {
		.Builder.AddTarget(.Builder)

		return nil
	}
}

// WithInfluxDBTarget adds an InfluxDB target to the graph.
func ( string,  ...influxdb.Option) Option {
	 := influxdb.New(, ...)

	return func( *Heatmap) error {
		.Builder.AddTarget(.Builder)

		return nil
	}
}

// WithStackdriverTarget adds a stackdriver query to the graph.
func ( *stackdriver.Stackdriver) Option {
	return func( *Heatmap) error {
		.Builder.AddTarget(.Builder)

		return nil
	}
}

// Span sets the width of the panel, in grid units. Should be a positive
// number between 1 and 12. Example: 6.
func ( float32) Option {
	return func( *Heatmap) error {
		if  < 1 ||  > 12 {
			return fmt.Errorf("span must be between 1 and 12: %w", errors.ErrInvalidArgument)
		}

		.Builder.Span = 

		return nil
	}
}

// Height sets the height of the panel, in pixels. Example: "400px".
func ( string) Option {
	return func( *Heatmap) error {
		.Builder.Height = &

		return nil
	}
}

// Description annotates the current visualization with a human-readable description.
func ( string) Option {
	return func( *Heatmap) error {
		.Builder.Description = &

		return nil
	}
}

// Transparent makes the background transparent.
func () Option {
	return func( *Heatmap) error {
		.Builder.Transparent = true

		return nil
	}
}

// Legend defines what should be shown in the legend.
func ( ...LegendOption) Option {
	return func( *Heatmap) error {
		for ,  := range  {
			if  == Hide {
				.Builder.HeatmapPanel.Legend.Show = false
			}
		}

		return nil
	}
}

// ShowZeroBuckets forces the display of "zero" buckets.
func () Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.HideZeroBuckets = false

		return nil
	}
}

// HideZeroBuckets hides "zero" buckets.
func () Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.HideZeroBuckets = true

		return nil
	}
}

// HighlightCards highlights bucket cards.
func () Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.HighlightCards = true

		return nil
	}
}

// NoHighlightCards disables the highlighting of bucket cards.
func () Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.HighlightCards = false

		return nil
	}
}

// ReverseYBuckets reverses the order of bucket on the Y-axis.
func () Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.ReverseYBuckets = true

		return nil
	}
}

// HideTooltip prevents the tooltip from being displayed.
func () Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.Tooltip.Show = false

		return nil
	}
}

// HideTooltipHistogram prevents the histograms from being displayed in tooltips.
// Histogram represents the distribution of the bucket values for the specific timestamp.
func () Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.Tooltip.ShowHistogram = false

		return nil
	}
}

// TooltipDecimals sets the number of decimals to be displayed in tooltips.
func ( int) Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.TooltipDecimals = 

		return nil
	}
}

// HideXAxis prevents the X-axis from being displayed.
func () Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.XAxis.Show = false

		return nil
	}
}

// YAxis configures the Y axis.
func ( ...axis.Option) Option {
	return func( *Heatmap) error {
		.Builder.HeatmapPanel.YAxis = *axis.New(...).Builder

		return nil
	}
}

// Repeat configures repeating a panel for a variable
func ( string) Option {
	return func( *Heatmap) error {
		.Builder.Repeat = &

		return nil
	}
}

// RepeatDirection configures repeating vertical or horizontal
func ( sdk.RepeatDirection) Option {
	return func( *Heatmap) error {
		.Builder.RepeatDirection = &

		return nil
	}
}